﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BotvaBot.Configuration;
using HttpRequester.RequestMakers.Base;
using System.Net;
using HttpRequester;
using System.Web;
using System.IO;
using System.Text.RegularExpressions;
using mshtml;
using Helpers;
using Helpers.Extensions;
using BotvaBot.RequestChains;
using BotvaBot.Configuration.Personaj;
using System.Threading;
using BotvaBot.RequestChainItems.Base;
using System.Reflection;
using HAP = HtmlAgilityPack;
using Common.Constants;
using HtmlParsing;
using BotvaBot.RequestChainItems;
using BotvaBot.Processor;
using System.Linq.Expressions;
using BotvaBot.RequestChains.Base;
using BotvaBot.BusinessLayer.Configuration.Personaj;
using BotvaBot.BusinessLayer.Enums;

namespace BotvaBot
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            Config.Custom.PersonajSet.Items.ForEach(personaj =>
                {
                    chblstPersonajesForSendBoat.Items.Add(personaj.Name, true);
                });

            var o = Config.Custom.PersonajSet.Items[0].KulonsLib;

            Config.Custom.PersonajSet.Items.ForEach(personaj =>
            {
                chblstPersonajesForWorkInKarier.Items.Add(personaj.Name, true);
            });

            Config.Custom.PersonajSet.Items.ForEach(personaj =>
            {
                lstBAPersonajes.Items.Add(personaj.Name, personaj.HasLetun > 0);
            });

            Func<object, ILoggable, bool> action = (args, loggable) =>
                {
                    loggable.OnSendLogMessage("Action done");
                    return true;
                };
            PeriodicProcessor<object> pp = new PeriodicProcessor<object>(action, null);
            ucTstPeriodicProcessing.ProcessManager = pp;
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);

            if (ThSendBoat != null)
            {
                ThSendBoat.Abort();
            }

            if (!CollectionHelper.IsNullOrEmpty(ThWorkInKariers))
            {
                foreach (string name in ThWorkInKariers.Keys)
                {
                    Thread th = ThWorkInKariers[name];
                    if(th != null)
                        th.Abort();
                }
            }
        }

        #region Hidden

        private void MainForm_Load(object sender, EventArgs e)
        {
            Hide();
            notifyIcon.Visible = true;
            WindowState = FormWindowState.Minimized;
        }

        private void MainForm_Resize(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
            {
                notifyIcon.Visible = true;
                Hide();
            }
        }

        private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            notifyIcon.Visible = false;
            Show();
            WindowState = FormWindowState.Normal;
        }

        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            notifyIcon.Visible = false;
        }

        #endregion Hidden



        #region Send Boat

        protected Thread ThSendBoat = null;

        protected volatile bool isSendBoatRun = false;

        protected static Dictionary<string, Dictionary<string, int>> SendBoatLog { get; set; }

        private void btnSendBoatServiceInit_Click(object sender, EventArgs e)
        {
            SendBoatData data = new SendBoatData();
            data.StartAfterMin = int.Parse(txtStartAfterMin.Text);
            data.RandomPauseMin = int.Parse(txtRandomPauseMin.Text);
            data.PeriodMin = int.Parse(txtPeriodMin.Text);
            data.Personajes = new List<PersonajCfg>();
            foreach (var item in chblstPersonajesForSendBoat.CheckedItems)
            {
                string name = item.ToString();
                PersonajCfg personaj = Config.Custom.PersonajSet.Items
                    .Where(p => p.Name == name).FirstOrDefault();
                if (personaj != null && (!data.Personajes.Contains(personaj)))
                    data.Personajes.Add(personaj);
            }
            data.MaxSendingsCount = int.Parse(txtMaxSendingsCount.Text);
            data.WorkingTimeStart = dtpWorkingTimeStart.Value;
            data.WorkingTimeEnd = dtpWorkingTimeEnd.Value;
            data.ReduceFirstTime = int.Parse(txtReduceFirstTime.Text);

            ThSendBoat = new Thread(new ParameterizedThreadStart(SendBoatRun));
            ThSendBoat.Start(data);

            btnSendBoatStart.Enabled = true;
            btnSendBoatStop.Enabled = false;
        }

        private void btnSendBoatStart_Click(object sender, EventArgs e)
        {
            isSendBoatRun = true;
            btnSendBoatStart.Enabled = false;
            btnSendBoatStop.Enabled = true;
        }

        private void btnSendBoatStop_Click(object sender, EventArgs e)
        {
            isSendBoatRun = false;
            btnSendBoatStart.Enabled = true;
            btnSendBoatStop.Enabled = false;
        }
        
        protected void SendBoatRun(object state)
        {
            SendBoatData data = state as SendBoatData;
            
            Random r = new Random();

            int shift = data.StartAfterMin * 60 * 1000;
            Thread.Sleep(shift);

            while (true)
            {
                DateTime dt;

                if (!isSendBoatRun)
                {
                    Thread.Sleep(1 * 60 * 1000);
                    continue;
                }

                dt = DateTime.Now;
                DateTime currWorkingTimeStart = new DateTime(dt.Year, dt.Month, dt.Day
                    , data.WorkingTimeStart.Hour, data.WorkingTimeStart.Minute, 0);
                DateTime currWorkingTimeEnd = new DateTime(dt.Year, dt.Month, dt.Day
                    , data.WorkingTimeEnd.Hour, data.WorkingTimeEnd.Minute, 0);
                if (dt < currWorkingTimeStart || dt > currWorkingTimeEnd)
                {
                    Thread.Sleep(1 * 60 * 1000);
                    continue;
                }

                dt = DateTime.Now;
                string msg = string.Format("[{0} {1}] {2}",
                    dt.ToShortDateString(), dt.ToShortTimeString(), "Start");

                if (LogHelper.Log != null)
                    LogHelper.Log.Info(msg);
                LogSendBoat(msg);

                foreach (PersonajCfg personaj in data.Personajes)
                {
                    dt = DateTime.Now;
                    string label = dt.ToString("yyyy-MM-dd");
                    if (SendBoatLog != null && SendBoatLog.ContainsKey(personaj.Name)
                        && SendBoatLog[personaj.Name].ContainsKey(label)
                        && SendBoatLog[personaj.Name][label] >= data.MaxSendingsCount)
                    {
                        continue;
                    }

                    SendBoatChain ch = new SendBoatChain();
                    ch.Personaj = personaj;

                    msg = string.Format("[{0} {1}] {2}",
                        dt.ToShortDateString(), dt.ToShortTimeString(), "Sending Start for " + personaj.Name);

                    if (LogHelper.Log != null)
                        LogHelper.Log.Info(msg);
                    LogSendBoat(msg);

                    ch.RunChain();
                    if (ch.IsSuccessfulyInvoked.HasValue && ch.IsSuccessfulyInvoked.Value)
                    {
                        if (SendBoatLog == null)
                            SendBoatLog = new Dictionary<string, Dictionary<string, int>>();
                        
                        if (!SendBoatLog.ContainsKey(personaj.Name))
                            SendBoatLog.Add(personaj.Name, new Dictionary<string, int>());

                        label = dt.ToString("yyyy-MM-dd");
                        if (SendBoatLog[personaj.Name].ContainsKey(label))
                            SendBoatLog[personaj.Name][label]++;
                        else
                            SendBoatLog[personaj.Name].Add(label, 1);
                    }

                    Thread.Sleep(r.Next(5) * 60 * 1000);

                    dt = DateTime.Now;
                    msg = string.Format("[{0} {1}] {2}",
                        dt.ToShortDateString(), dt.ToShortTimeString(), "Sending Stop for " + personaj.Name);

                    if (LogHelper.Log != null)
                        LogHelper.Log.Info(msg);
                    LogSendBoat(msg);

                    int persPause = r.Next(5) * 60 * 1000;
                    //int persPause = r.Next(5) * 1000;
                    Thread.Sleep(persPause);

                    if (SendBoatLog != null && SendBoatLog.ContainsKey(personaj.Name))
                    {
                        label = dt.AddDays(-2).ToString("yyyy-MM-dd");
                        if (SendBoatLog[personaj.Name].ContainsKey(label))
                            SendBoatLog[personaj.Name].Remove(label);
                    }
                }

                dt = DateTime.Now;
                msg = string.Format("[{0} {1}] {2}",
                    dt.ToShortDateString(), dt.ToShortTimeString(), "Stop");

                if (LogHelper.Log != null)
                    LogHelper.Log.Info(msg);
                LogSendBoat(msg);

                Thread.Sleep(data.PeriodMin * 60 * 1000);
                //Thread.Sleep(data.PeriodMin * 1000);
                
                int pause = (r.Next(data.RandomPauseMin) + 5) * 60 * 1000;
                //int pause = (r.Next(data.RandomPauseMin) + 5) * 1000;
                Thread.Sleep(pause);
            }
        }

        public class SendToBigAdventureData
        {
            public List<PersonajCfg> Personajes { get; set; }

            public int StartAfterMin { get; set; }
            public int RandomPauseMin { get; set; }
            public int PeriodMin { get; set; }
            public int MaxSendingsCount { get; set; }
            public DateTime WorkingTimeStart { get; set; }
            public DateTime WorkingTimeEnd { get; set; }
            public int ReduceFirstTime { get; set; }
        }


        public class SendBoatData
        {
            public List<PersonajCfg> Personajes { get; set; }

            public int StartAfterMin { get; set; }
            public int RandomPauseMin { get; set; }
            public int PeriodMin { get; set; }
            public int MaxSendingsCount { get; set; }
            public DateTime WorkingTimeStart { get; set; }
            public DateTime WorkingTimeEnd { get; set; }
            public int ReduceFirstTime { get; set; }
        }

        protected const int MAX_LOG_COUNT = 20;
        protected object lbxLog_lock = new object();

        protected void LogSendBoat(string message)
        {
            if (lbxLog.InvokeRequired)
                lbxLog.Invoke(new MethodInvoker(delegate() { LogSendBoat(message); }));
            else
            {
                lock(lbxLog_lock)
                {
                    if (lbxLog.Items.Count >= MAX_LOG_COUNT)
                    {
                        while (lbxLog.Items.Count >= MAX_LOG_COUNT)
                        {
                            lbxLog.Items.RemoveAt(0);
                        }
                    }
                    lbxLog.Items.Add(message);
                }
            }
        }

        #endregion Send Boat


        #region Work in Karier

        protected Dictionary<string, Thread> ThWorkInKariers = null;

        protected volatile bool isWorkInKarierRun = false;

        protected static object lockWorkInKarierLog = new object();
        protected static Dictionary<string, Dictionary<string, int>> WorkInKarierLog { get; set; }


        private void btnWorkInKarierServiceInit_Click(object sender, EventArgs e)
        {
            ThWorkInKariers = new Dictionary<string, Thread>();

            foreach (var item in chblstPersonajesForWorkInKarier.CheckedItems)
            {
                WorkInKarierData data = new WorkInKarierData();
                data.StartAfterMin = int.Parse(txtStartAfterMinForWorkInKarier.Text);
                data.RandomPauseMin = int.Parse(txtRandomPauseMinForWorkInKarier.Text);
                data.PeriodMin = int.Parse(txtPeriodMinForWorkInKarier.Text);
                data.MaxSendingsCount = int.Parse(txtMaxSendingsCountForWorkInKarier.Text);
                data.WorkingTimeStart = dtpWorkingTimeForWorkToKarierStart.Value;
                data.WorkingTimeEnd = dtpWorkingTimeForWorkToKarierEnd.Value;
                data.ReduceFirstTime = int.Parse(txtReduceFirstTimeForWorkInKarier.Text);

                string name = item.ToString();
                PersonajCfg personaj = Config.Custom.PersonajSet.Items
                    .Where(p => p.Name == name).FirstOrDefault();
                if (personaj != null && (!ThWorkInKariers.ContainsKey(name)))
                {
                    data.Personaj = personaj;

                    Thread th = new Thread(new ParameterizedThreadStart(WorkInKarierForPersonajRun));
                    ThWorkInKariers.Add(name, th);
                    th.Start(data);
                }
            }

            btnWorkInKarierServiceStart.Enabled = true;
            btnWorkInKarierServiceStop.Enabled = false;
        }

        private void btnWorkInKarierServiceStart_Click(object sender, EventArgs e)
        {
            isWorkInKarierRun = true;
            btnWorkInKarierServiceStart.Enabled = false;
            btnWorkInKarierServiceStop.Enabled = true;
        }

        private void btnWorkInKarierServiceStop_Click(object sender, EventArgs e)
        {
            isWorkInKarierRun = false;
            btnWorkInKarierServiceStart.Enabled = true;
            btnWorkInKarierServiceStop.Enabled = false;
        }

        private void btnWorkInKarierServicePause_Click(object sender, EventArgs e)
        { }

        protected static int Minute { get { return 1000 * 60; } }

        protected void WorkInKarierForPersonajRun(object state)
        {
            WorkInKarierData data = state as WorkInKarierData;
            PersonajCfg personaj = data.Personaj;

            Random r = new Random();

            SendLogForWorkInKarier("Service is started", personaj);

            SendLogForWorkInKarier("Service us Shifted to {0} minutes", personaj, data.StartAfterMin);
            Sleep(data.StartAfterMin);
            SendLogForWorkInKarier("Service Shift is finished", personaj);

            int countForMonster = 0;

            while (true)
            {
                SendLogForWorkInKarier("Service MainLoop is Started", personaj);

                DateTime dt = DateTime.Now;

                bool isInvokationNeeded = true;
                isInvokationNeeded &= isWorkInKarierRun;

                DateTime currWorkingTimeStart = new DateTime(dt.Year, dt.Month, dt.Day
                    , data.WorkingTimeStart.Hour, data.WorkingTimeStart.Minute, 0);
                DateTime currWorkingTimeEnd = new DateTime(dt.Year, dt.Month, dt.Day
                    , data.WorkingTimeEnd.Hour, data.WorkingTimeEnd.Minute, 0);
                if (currWorkingTimeEnd < currWorkingTimeStart)
                    currWorkingTimeEnd = currWorkingTimeEnd.AddDays(1);
                isInvokationNeeded &= (dt >= currWorkingTimeStart && dt <= currWorkingTimeEnd);

                string label = dt.ToString("yyyy-MM-dd");
                isInvokationNeeded &= (WorkInKarierLog == null
                    || (!WorkInKarierLog.ContainsKey(personaj.Name))
                    || (!WorkInKarierLog[personaj.Name].ContainsKey(label))
                    || (WorkInKarierLog[personaj.Name][label] < data.MaxSendingsCount));

                if(!isInvokationNeeded)
                {
                    SendLogForWorkInKarier("Service MainLoop is Terminated", personaj);
                    Sleep(1);
                    continue;
                }

                if (personaj.KulonsLib.ContainsKey(Kulon.Antimag))
                {
                    PersonajInfo pi = new PersonajInfo(personaj);
                    TimeSpan saveTime = pi.GetSaveTime();
                    if (saveTime.TotalMinutes <= 5)
                    {
                        ActivateKulonChain akch = new ActivateKulonChain();
                        akch.Personaj = personaj;
                        akch.KulonType = Kulon.Antimag;
                        akch.RunChain();
                    }
                    else
                    {
                        if (personaj.KulonsLib.ContainsKey(Kulon.KopiKrist))
                        {
                            ActivateKulonChain akch3 = new ActivateKulonChain();
                            akch3.Personaj = personaj;
                            akch3.KulonType = Kulon.KopiKrist;
                            akch3.RunChain();
                        }
                    }
                }
                
                
                SendLogForWorkInKarier("Work to Karier is Started", personaj);

                WorkInKarierChain ch = new WorkInKarierChain();
                ch.Personaj = personaj;
                ch.RunChain();
                
                SendLogForWorkInKarier("Work to Karier is Finished", personaj);

                if (ch.IsSuccessfulyInvoked.HasValue && (!ch.IsSuccessfulyInvoked.Value))
                {
                    SendLogForWorkInKarier("Work to Karier was Failed", personaj);
                    Sleep(1);
                }

                SendLogForWorkInKarier("Waiting in Karier is Started", personaj);
                Sleep(data.PeriodMin);
                Sleep(data.RandomPauseMin, r);
                SendLogForWorkInKarier("Waiting in Karier is Finished", personaj);

                SendLogForWorkInKarier("Try to Get a Cristall is Started", personaj);

                TryGetCristalChain ch1 = new TryGetCristalChain();
                ch1.Personaj = personaj;
                ch1.RunChain();

                SendLogForWorkInKarier("Try to Get a Cristall is Finished", personaj);


                if (ch1.IsSuccessfulyInvoked.HasValue && ch1.IsSuccessfulyInvoked.Value)
                {
                    int quantity = AddAndClearWorkInKarierLog(personaj, dt);
                    SendLogForWorkInKarier("Try to Get a Cristall was Success ({0})", personaj, quantity);
                }
                else
                {
                    SendLogForWorkInKarier("Try to Get a Cristall was Failed", personaj);
                }

                Thread.Sleep(1000);

                if (personaj.KulonsLib.ContainsKey(Kulon.Antimag))
                {
                    PersonajInfo pi1 = new PersonajInfo(personaj);
                    TimeSpan saveTime1 = pi1.GetSaveTime();
                    if (saveTime1.TotalMinutes <= 5)
                    {
                        ActivateKulonChain akch1 = new ActivateKulonChain();
                        akch1.Personaj = personaj;
                        akch1.KulonType = Kulon.Antimag;
                        akch1.RunChain();
                    }
                    else
                    {
                        if (personaj.KulonsLib.ContainsKey(Kulon.KopiKrist))
                        {
                            ActivateKulonChain akch2 = new ActivateKulonChain();
                            akch2.Personaj = personaj;
                            akch2.KulonType = Kulon.KopiKrist;
                            akch2.RunChain();
                        }
                    }
                }

                if (countForMonster == 0)
                {
                    try
                    {
                        SendLogForWorkInKarier("Try Fight With Monster Start", personaj);
                        FightWithMonsterChain ch2 = new FightWithMonsterChain();
                        ch2.Personaj = personaj;
                        ch2.RunChain();
                        SendLogForWorkInKarier("Try Fight With Monster Finish", personaj);
                    }
                    catch (Exception ee)
                    {
                        SendLogForWorkInKarier("Try Fight With Monster Failed: " + ee.Message, personaj);
                    }
                }
                countForMonster++;
                if (countForMonster == Config.Custom.MonsterFightDelitel)
                    countForMonster = 0;

                Sleep(data.RandomPauseMin, null);

                SendLogForWorkInKarier("Service MainLoop is Finished", personaj);
            }
        }

        public class WorkInKarierData
        {
            public PersonajCfg Personaj { get; set; }

            public int StartAfterMin { get; set; }
            public int RandomPauseMin { get; set; }
            public int PeriodMin { get; set; }
            public int MaxSendingsCount { get; set; }
            public DateTime WorkingTimeStart { get; set; }
            public DateTime WorkingTimeEnd { get; set; }
            public int ReduceFirstTime { get; set; }
        }


        protected object txtLogForWorkInKarier_lock = new object();

        protected void LogWorkInKarier(string message)
        {
            if (txtLogForWorkInKarier.InvokeRequired)
                txtLogForWorkInKarier.Invoke(new MethodInvoker(delegate() { LogWorkInKarier(message); }));
            else
            {
                lock (txtLogForWorkInKarier_lock)
                {
                    if (txtLogForWorkInKarier.Items.Count >= MAX_LOG_COUNT)
                    {
                        while (txtLogForWorkInKarier.Items.Count >= MAX_LOG_COUNT)
                        {
                            txtLogForWorkInKarier.Items.RemoveAt(0);
                        }
                    }
                    txtLogForWorkInKarier.Items.Add(message);
                }
            }
        }

        private void SendLogForWorkInKarier(string format, PersonajCfg personaj, params object[] args)
        {
            string message = string.Format(format, args);
            SendLogForWorkInKarier(message, personaj);
        }
        
        private void SendLogForWorkInKarier(string message, PersonajCfg personaj)
        {
            DateTime dt = DateTime.Now;
            string time = dt.ToString("yyyy-MM-dd HH:mm:ss");
            string name = personaj.Name.PadRight(10, ' ');

            string logMessage = string.Format("[{0}] - [{1}] : {2}", time, name, message);
            
            if (LogHelper.Log != null)
                LogHelper.Log.Info(logMessage);

            LogWorkInKarier(logMessage);
        }

        public void Sleep(int max)
        {
            Sleep(max, null);
        }

        public void Sleep(int max, Random r)
        {
            int timeout = r == null ? max : r.Next(max);
            timeout *= Minute;
            Thread.Sleep(timeout);
        }

        protected int AddAndClearWorkInKarierLog(PersonajCfg personaj, DateTime dt)
        {
            int result = 0;
            lock (lockWorkInKarierLog)
            {
                if (WorkInKarierLog == null)
                    WorkInKarierLog = new Dictionary<string, Dictionary<string, int>>();

                if (!WorkInKarierLog.ContainsKey(personaj.Name))
                    WorkInKarierLog.Add(personaj.Name, new Dictionary<string, int>());

                string label = dt.ToString("yyyy-MM-dd");
                if (WorkInKarierLog[personaj.Name].ContainsKey(label))
                    WorkInKarierLog[personaj.Name][label]++;
                else
                    WorkInKarierLog[personaj.Name].Add(label, 1);

                result = WorkInKarierLog[personaj.Name][label];
            }

            return result;
        }

        #endregion Work in Karier


        #region Send To Big Adventure

        protected Thread ThSendToBigAdventure = null;

        private void btnBAInit_Click(object sender, EventArgs e)
        {
            SendToBigAdventureData data = new SendToBigAdventureData();
            data.StartAfterMin = int.Parse(txtBAStartAfter.Text);
            data.RandomPauseMin = int.Parse(txtBAPause.Text);
            data.PeriodMin = int.Parse(txtBAPeriod.Text);
            data.Personajes = new List<PersonajCfg>();
            foreach (var item in lstBAPersonajes.CheckedItems)
            {
                string name = item.ToString();
                PersonajCfg personaj = Config.Custom.PersonajSet.Items
                    .Where(p => p.Name == name).FirstOrDefault();
                if (personaj != null && (!data.Personajes.Contains(personaj)))
                    data.Personajes.Add(personaj);
            }
            data.MaxSendingsCount = int.Parse(txtBAMaxCount.Text);
            data.WorkingTimeStart = dtBAWorkingTimeFrom.Value;
            data.WorkingTimeEnd = dtBAWorkingTimeTill.Value;
            data.ReduceFirstTime = int.Parse(txtBAReduceFirstTime.Text);

            ThSendToBigAdventure = new Thread(new ParameterizedThreadStart(SendToBigAdventureRun));
            ThSendToBigAdventure.Start(data);

            btnBAStart.Enabled = true;
            btnBAStop.Enabled = false;

        }

        protected volatile bool isSendToBigAdventureRun = false;

        private void btnBAStart_Click(object sender, EventArgs e)
        {
            isSendToBigAdventureRun = true;
            btnBAStart.Enabled = false;
            btnBAStop.Enabled = true;
        }

        private void btnBAStop_Click(object sender, EventArgs e)
        {
            isSendToBigAdventureRun = false;
            btnBAStart.Enabled = true;
            btnBAStop.Enabled = false;
        }

        protected static Dictionary<string, Dictionary<string, int>> SendToBigAdventureLog { get; set; }

        protected void SendToBigAdventureRun(object state)
        {
            SendToBigAdventureData data = state as SendToBigAdventureData;

            Random r = new Random();

            int shift = data.StartAfterMin * 60 * 1000;
            Thread.Sleep(shift);

            while (true)
            {
                DateTime dt;

                if (!isSendToBigAdventureRun)
                {
                    Thread.Sleep(1 * 60 * 1000);
                    continue;
                }

                dt = DateTime.Now;
                DateTime currWorkingTimeStart = new DateTime(dt.Year, dt.Month, dt.Day
                    , data.WorkingTimeStart.Hour, data.WorkingTimeStart.Minute, 0);
                DateTime currWorkingTimeEnd = new DateTime(dt.Year, dt.Month, dt.Day
                    , data.WorkingTimeEnd.Hour, data.WorkingTimeEnd.Minute, 0);
                if (currWorkingTimeEnd <= currWorkingTimeStart)
                    currWorkingTimeEnd = currWorkingTimeEnd.AddDays(1);
                if (dt < currWorkingTimeStart || dt > currWorkingTimeEnd)
                {
                    Thread.Sleep(1 * 60 * 1000);
                    continue;
                }

                dt = DateTime.Now;
                string msg = string.Format("[{0} {1}] {2}",
                    dt.ToShortDateString(), dt.ToShortTimeString(), "Start");

                if (LogHelper.Log != null)
                    LogHelper.Log.Info(msg);
                LogSendToBigAdventure(msg);

                foreach (PersonajCfg personaj in data.Personajes)
                {
                    foreach (LetunCfg letun in personaj.WarGildia.LetunSet.Items)
                    {
                        dt = DateTime.Now;
                        string label = dt.ToString("yyyy-MM-dd");
                        if (SendToBigAdventureLog != null && SendToBigAdventureLog.ContainsKey(letun.Name)
                            && SendToBigAdventureLog[letun.Name].ContainsKey(label)
                            && SendToBigAdventureLog[letun.Name][label] >= data.MaxSendingsCount)
                        {
                            continue;
                        }


                        SendLetunToBigAdventureChain ch = new SendLetunToBigAdventureChain();
                        ch.Personaj = personaj;
                        ch.GildiaId = personaj.WarGildia.GildiaId;
                        ch.LetunId = letun.ID;

                        msg = string.Format("[{0} {1}] {2}",
                            dt.ToShortDateString(), dt.ToShortTimeString(), "Sending Start for " + personaj.Name + " - " + letun.Name);

                        if (LogHelper.Log != null)
                            LogHelper.Log.Info(msg);
                        LogSendToBigAdventure(msg);

                        ch.RunChain();
                        if (ch.IsSuccessfulyInvoked.HasValue && ch.IsSuccessfulyInvoked.Value)
                        {
                            if (SendToBigAdventureLog == null)
                                SendToBigAdventureLog = new Dictionary<string, Dictionary<string, int>>();

                            if (!SendToBigAdventureLog.ContainsKey(letun.Name))
                                SendToBigAdventureLog.Add(letun.Name, new Dictionary<string, int>());

                            label = dt.ToString("yyyy-MM-dd");
                            if (SendToBigAdventureLog[letun.Name].ContainsKey(label))
                                SendToBigAdventureLog[letun.Name][label]++;
                            else
                                SendToBigAdventureLog[letun.Name].Add(label, 1);
                        }

                        Thread.Sleep(r.Next(10) * 1000);

                        dt = DateTime.Now;
                        msg = string.Format("[{0} {1}] {2}",
                            dt.ToShortDateString(), dt.ToShortTimeString(), "Sending Stop for " + personaj.Name + " - " + letun.Name);

                        if (LogHelper.Log != null)
                            LogHelper.Log.Info(msg);
                        LogSendToBigAdventure(msg);

                        //int persPause = r.Next(5) * 60 * 1000;
                        //int persPause = r.Next(5) * 1000;
                        //Thread.Sleep(persPause);

                        if (SendToBigAdventureLog != null && SendToBigAdventureLog.ContainsKey(letun.Name))
                        {
                            label = dt.AddDays(-2).ToString("yyyy-MM-dd");
                            if (SendToBigAdventureLog[letun.Name].ContainsKey(label))
                                SendToBigAdventureLog[letun.Name].Remove(label);
                        }
                    }

                    dt = DateTime.Now;
                    msg = string.Format("[{0} {1}] {2}",
                        dt.ToShortDateString(), dt.ToShortTimeString(), "Stop");

                    if (LogHelper.Log != null)
                        LogHelper.Log.Info(msg);
                    LogSendToBigAdventure(msg);
                }

                Thread.Sleep(data.PeriodMin * 60 * 1000);
                //Thread.Sleep(data.PeriodMin * 1000);

                int pause = (r.Next(data.RandomPauseMin) + 3) * 60 * 1000;
                //int pause = (r.Next(data.RandomPauseMin) + 5) * 1000;
                Thread.Sleep(pause);
            }
        }


        protected object lbxBALog_lock = new object();
        protected void LogSendToBigAdventure(string message)
        {
            if (lstBALog.InvokeRequired)
                lstBALog.Invoke(new MethodInvoker(delegate() { LogSendToBigAdventure(message); }));
            else
            {
                lock (lbxBALog_lock)
                {
                    if (lstBALog.Items.Count >= MAX_LOG_COUNT)
                    {
                        while (lstBALog.Items.Count >= MAX_LOG_COUNT)
                        {
                            lstBALog.Items.RemoveAt(0);
                        }
                    }
                    lstBALog.Items.Add(message);
                }
            }
        }

        #endregion Send To Big Adventure

        private void btnShowCommadsTestingForm_Click(object sender, EventArgs e)
        {
            TestCommandsForm frm = new TestCommandsForm();
            frm.ShowDialog();
        }

        private void btnShowNewCommandsForm_Click(object sender, EventArgs e)
        {
            NewMainForm frm = new NewMainForm();
            frm.ShowDialog();
        }

        private void btnGetSaveTime_Click(object sender, EventArgs e)
        {
            PersonajCfg personaj = Config.Custom.PersonajSet.Items.Where(p => p.Name == "Scilurus").FirstOrDefault();
            int value = (int)new PersonajInfo(personaj).GetSaveTime().TotalMilliseconds;
            MessageBox.Show(value.ToString());
        }

        private void btnActivateKulon_Click(object sender, EventArgs e)
        {
            PersonajCfg personaj = Config.Custom.PersonajSet.Items.Where(p => p.Name == "Scilurus").FirstOrDefault();
            ActivateKulonChain ch = new ActivateKulonChain();
            ch.Personaj = personaj;
            ch.KulonType = Kulon.Igroman;
            ch.RunChain();
            bool isSuccess = ch.IsSuccessfulyInvoked.HasValue && ch.IsSuccessfulyInvoked.Value;
            MessageBox.Show(isSuccess.ToString().ToUpper());
        }

    }
}
